﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace XmlStudio.DataLayer {
    /// <summary>
    /// Helper class for XSD data types.
    /// </summary>
    public class XsdDataTypeHelper {
        #region Fields
        private static List<XsdBuiltInDataType> builtInXsdTypes = new List<XsdBuiltInDataType>{
                XsdBuiltInDataType.AnyUri,
                XsdBuiltInDataType.Base64Binary,
                XsdBuiltInDataType.Boolean,
                XsdBuiltInDataType.Byte,
                XsdBuiltInDataType.Date,
                XsdBuiltInDataType.DateTime,
                XsdBuiltInDataType.Decimal,
                XsdBuiltInDataType.Double,
                XsdBuiltInDataType.Duration,
                XsdBuiltInDataType.Entities,
                XsdBuiltInDataType.Entity,
                XsdBuiltInDataType.Float,
                XsdBuiltInDataType.GDay,
                XsdBuiltInDataType.GMonth,
                XsdBuiltInDataType.GMonthDay,
                XsdBuiltInDataType.GYear,
                XsdBuiltInDataType.GYearMonth,
                XsdBuiltInDataType.HexBinary,
                XsdBuiltInDataType.Id,
                XsdBuiltInDataType.IdRef,
                XsdBuiltInDataType.IdRefs,
                XsdBuiltInDataType.Int,
                XsdBuiltInDataType.Integer,
                XsdBuiltInDataType.Language,
                XsdBuiltInDataType.Long,
                XsdBuiltInDataType.Name,
                XsdBuiltInDataType.NCName,
                XsdBuiltInDataType.NegativeInteger,
                XsdBuiltInDataType.NMToken,
                XsdBuiltInDataType.NMTokens,
                XsdBuiltInDataType.NonNegativeInteger,
                XsdBuiltInDataType.NonPositiveInteger,
                XsdBuiltInDataType.NormalizedString,
                XsdBuiltInDataType.Notation,
                XsdBuiltInDataType.PositiveInteger,
                XsdBuiltInDataType.QName,
                XsdBuiltInDataType.Short,
                XsdBuiltInDataType.String,
                XsdBuiltInDataType.Time,
                XsdBuiltInDataType.Token,
                XsdBuiltInDataType.UnsignedByte,
                XsdBuiltInDataType.UnsignedInt,
                XsdBuiltInDataType.UnsignedLong,
                XsdBuiltInDataType.UnsignedShort,
            };

        private static List<string> builtInXsdTypesString = new List<string> {
            "anyUri",
            "base64Binary",
            "boolean",
            "byte",
            "date",
            "dateTime",
            "decimal",
            "double",
            "duration",
            "ENTITIES",
            "ENTITY",
            "float",
            "gDay",
            "gMonth",
            "gMonthDay",
            "gYear",
            "gYearMonth",
            "hexBinary",
            "ID",
            "IDREF",
            "IDREFS",
            "int",
            "integer",
            "language",
            "long",
            "Name",
            "NCName",
            "negativeInteger",
            "NMTOKEN",
            "NMTOKENS",
            "nonNegativeInteger",
            "nonPositiveInteger",
            "normalizedString",
            "NOTATION",
            "positiveInteger",
            "QName",
            "short",
            "string",
            "time",
            "token",
            "unsignedInt",
            "unsignedLong",
            "unsignedShort"
        };
        #endregion

        /// <summary>
        /// Lists the built in XSD types.
        /// </summary>
        /// <returns>Collection of built in data types.</returns>
        public static IEnumerable<XsdBuiltInDataType> ListBuiltInXsdTypes() {
            return builtInXsdTypes;
        }

        /// <summary>
        /// Lists the built in XSD types string.
        /// </summary>
        /// <returns>Collection of built in data types.</returns>
        public static IEnumerable<string> ListBuiltInXsdTypesString() {
            return builtInXsdTypesString;
        }

        /// <summary>
        /// Lists the built in XSD types tuple.
        /// </summary>
        /// <returns>Collection of built in data types.</returns>
        public static IEnumerable<Tuple<XsdBuiltInDataType, string>> ListBuiltInXsdTypesTuple() {
            var res = builtInXsdTypes.Zip(builtInXsdTypesString, (x, y) => new Tuple<XsdBuiltInDataType, string>(x, y));
            return res;
        }

        /// <summary>
        /// Gets the type from string.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>XSD data type or null.</returns>
        public static XsdBuiltInDataType? GetTypeFromString(string type) {
            switch(type.ToLower()) {
                case "anyuri":
                    return XsdBuiltInDataType.AnyUri;
                case "base64binary":
                    return XsdBuiltInDataType.Base64Binary;
                case "boolean":
                    return XsdBuiltInDataType.Boolean;
                case "byte":
                    return XsdBuiltInDataType.Byte;
                case "date":
                    return XsdBuiltInDataType.Date;
                case "datetime":
                    return XsdBuiltInDataType.DateTime;
                case "decimal":
                    return XsdBuiltInDataType.Decimal;
                case "double":
                    return XsdBuiltInDataType.Double;
                case "duration":
                    return XsdBuiltInDataType.Duration;
                case "entities":
                    return XsdBuiltInDataType.Entities;
                case "entity":
                    return XsdBuiltInDataType.Entity;
                case "float":
                    return XsdBuiltInDataType.Float;
                case "gday":
                    return XsdBuiltInDataType.GDay;
                case "gmonth":
                    return XsdBuiltInDataType.GMonth;
                case "gmonthday":
                    return XsdBuiltInDataType.GMonthDay;
                case "gyear":
                    return XsdBuiltInDataType.GYear;
                case "gyearmonth":
                    return XsdBuiltInDataType.GYearMonth;
                case "hexbinary":
                    return XsdBuiltInDataType.HexBinary;
                case "id":
                    return XsdBuiltInDataType.Id;
                case "idref":
                    return XsdBuiltInDataType.IdRef;
                case "idrefs":
                    return XsdBuiltInDataType.IdRefs;
                case "int":
                    return XsdBuiltInDataType.Int;
                case "integer":
                    return XsdBuiltInDataType.Integer;
                case "language":
                    return XsdBuiltInDataType.Language;
                case "long":
                    return XsdBuiltInDataType.Long;
                case "name":
                    return XsdBuiltInDataType.Name;
                case "ncname":
                    return XsdBuiltInDataType.NCName;
                case "negativeinteger":
                    return XsdBuiltInDataType.NegativeInteger;
                case "nmtoken":
                    return XsdBuiltInDataType.NMToken;
                case "nmtokens":
                    return XsdBuiltInDataType.NMTokens;
                case "nonnegativeinteger":
                    return XsdBuiltInDataType.NonNegativeInteger;
                case "nonpositiveinteger":
                    return XsdBuiltInDataType.NonPositiveInteger;
                case "normalizedstring":
                    return XsdBuiltInDataType.NormalizedString;
                case "notation":
                    return XsdBuiltInDataType.Notation;
                case "positiveinteger":
                    return XsdBuiltInDataType.PositiveInteger;
                case "qname":
                    return XsdBuiltInDataType.QName;
                case "short":
                    return XsdBuiltInDataType.Short;
                case "string":
                    return XsdBuiltInDataType.String;
                case "time":
                    return XsdBuiltInDataType.Time;
                case "token":
                    return XsdBuiltInDataType.Token;
                case "unsignedbyte":
                    return XsdBuiltInDataType.UnsignedByte;
                case "unsignedint":
                    return XsdBuiltInDataType.UnsignedInt;
                case "unsignedlong":
                    return XsdBuiltInDataType.UnsignedLong;
                case "unsignedshort":
                    return XsdBuiltInDataType.UnsignedShort;
                default:
                    return null;
            }
        }

        /// <summary>
        /// Gets the name of the type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>Type name.</returns>
        public static string GetTypeName(XsdBuiltInDataType type) {
            switch(type) {
                case XsdBuiltInDataType.AnyUri:
                    return "anyUri";
                case XsdBuiltInDataType.Base64Binary:
                    return "base64Binary";
                case XsdBuiltInDataType.Boolean:
                    return "boolean";
                case XsdBuiltInDataType.Byte:
                    return "byte";
                case XsdBuiltInDataType.Date:
                    return "date";
                case XsdBuiltInDataType.DateTime:
                    return "dateTime";
                case XsdBuiltInDataType.Decimal:
                    return "decimal";
                case XsdBuiltInDataType.Double:
                    return "double";
                case XsdBuiltInDataType.Duration:
                    return "duration";
                case XsdBuiltInDataType.Entities:
                    return "ENTITIES";
                case XsdBuiltInDataType.Entity:
                    return "ENTITY";
                case XsdBuiltInDataType.Float:
                    return "float";
                case XsdBuiltInDataType.GDay:
                    return "gDay";
                case XsdBuiltInDataType.GMonth:
                    return "gMonth";
                case XsdBuiltInDataType.GMonthDay:
                    return "gMonthDay";
                case XsdBuiltInDataType.GYear:
                    return "gYear";
                case XsdBuiltInDataType.GYearMonth:
                    return "gYearMonth";
                case XsdBuiltInDataType.HexBinary:
                    return "hexBinary";
                case XsdBuiltInDataType.Id:
                    return "ID";
                case XsdBuiltInDataType.IdRef:
                    return "IDREF";
                case XsdBuiltInDataType.IdRefs:
                    return "IDREFS";
                case XsdBuiltInDataType.Int:
                    return "int";
                case XsdBuiltInDataType.Integer:
                    return "integer";
                case XsdBuiltInDataType.Language:
                    return "language";
                case XsdBuiltInDataType.Long:
                    return "long";
                case XsdBuiltInDataType.Name:
                    return "Name";
                case XsdBuiltInDataType.NCName:
                    return "NCName";
                case XsdBuiltInDataType.NegativeInteger:
                    return "negativeInteger";
                case XsdBuiltInDataType.NMToken:
                    return "NMTOKEN";
                case XsdBuiltInDataType.NMTokens:
                    return "NMTOKENS";
                case XsdBuiltInDataType.NonNegativeInteger:
                    return "nonNegativeInteger";
                case XsdBuiltInDataType.NonPositiveInteger:
                    return "nonPositiveInteger";
                case XsdBuiltInDataType.NormalizedString:
                    return "normalizedString";
                case XsdBuiltInDataType.Notation:
                    return "NOTATION";
                case XsdBuiltInDataType.PositiveInteger:
                    return "positiveInteger";
                case XsdBuiltInDataType.QName:
                    return "QName";
                case XsdBuiltInDataType.Short:
                    return "short";
                case XsdBuiltInDataType.String:
                    return "string";
                case XsdBuiltInDataType.Time:
                    return "time";
                case XsdBuiltInDataType.Token:
                    return "token";
                case XsdBuiltInDataType.UnsignedByte:
                    return "unsignedByte";
                case XsdBuiltInDataType.UnsignedInt:
                    return "unsignedInt";
                case XsdBuiltInDataType.UnsignedLong:
                    return "unsignedLong";
                case XsdBuiltInDataType.UnsignedShort:
                    return "unsignedShort";
                default:
                    return string.Empty;
            }
        }
    }
}